import layerMap from './layerMap'
import Marker from "./plugin/Marker";
import Popup from "./plugin/Popup"

/**
 * 图层类
 * 图层id的命名方式如下：
 *  - 图层类型 + 下划线 + 用户命名的id
 *  图层类型_ 没有的话会自动插入，有的话将跳过 用用户命名的id
 *
 *  fill 图层添加 外边框的话 命名格式 为 fill_outline_ + id
 */
class LayerManager{
    map
    layerMap
    constructor(map) {
        this.layerMap = new layerMap()
        this.map = map
    }

    /**
     * 添加栅格瓦片图层
     * @param key  图层名称
     * @param options   rasterDem 配置项
     */
    addRasterLayer(key, sourceOptions, layerOptions, beforeId) {
        let opt = {
            type: 'raster',
            tiles: ['https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg'],
            tileSize: 512,
            minZoom: 0,
            maxZoom: 22,
            scheme: 'xyz',
        }
        Object.assign(opt, sourceOptions)
        this.map.on('load', () => {
            this.map.addSource(key, {
                ...opt
            })
            let l_opt = {
                type: 'raster',
                source: key,
                id: key,
                minZoom: 0,
                maxZoom: 22
            }
            Object.assign(l_opt, layerOptions)
            this.map.addLayer({
                ...l_opt
            }, beforeId)
        })
    }

    /**
     * 添加 dem图层
     * @param key   图层名称
     * @param options   配置项
     */
    addRasterDemLayer(key, options) {
        let opt = {
            type: 'raster-dem',
            tiles: [],
            url: 'mapbox://mapbox.mapbox-terrain-dem-v1',
            tileSize: 512,
            maxZoom: 20,
            minZoom: 0,
            encoding: 'terrarium'
        }
        Object.assign(opt, options)
        this.map.on('style.load', () => {
            this.map.addSource(key, {
                ...opt
            })
        })
        map.setTerrain({ 'source': key, 'exaggeration': 1.5 });
    }

    // 添加 geoJson数据格式的图层
    addGeoJsonLayer(key, sourceOptions, layerOption, beforeId) {
        let opt = {
            type: 'geojson',
            data: {
                'type': 'Feature',
                'properties': {},
                'geometry': {
                    'type': 'LineString',
                    'coordinates': [
                        [-122.483696, 37.833818],
                        [-122.483482, 37.833174],
                        [-122.483396, 37.8327],
                        [-122.483568, 37.832056],
                        [-122.48404, 37.831141],
                        [-122.48404, 37.830497],
                        [-122.483482, 37.82992],
                        [-122.483568, 37.829548],
                        [-122.48507, 37.829446],
                        [-122.4861, 37.828802],
                        [-122.486958, 37.82931],
                        [-122.487001, 37.830802],
                        [-122.487516, 37.831683],
                        [-122.488031, 37.832158],
                        [-122.488889, 37.832971],
                        [-122.489876, 37.832632],
                        [-122.490434, 37.832937],
                        [-122.49125, 37.832429],
                        [-122.491636, 37.832564],
                        [-122.492237, 37.833378],
                        [-122.493782, 37.833683]
                    ]
                }
            },
            // generateId: true,
            // cluster: true,
            // clusterRadius: 50,
            // clusterMaxZoom: 12,
            // clusterMinPoints: 5
        }
        Object.assign(opt, sourceOptions)
        this.map.on('load', () => {
            this.map.addSource(key, {
                ...opt
            })

            let l_opt = {
                id: key,
                source: key,
                type: 'line'
            }
            Object.assign(l_opt, layerOption)
            if (l_opt.type === 'line') {
                this.addLineLayer(l_opt, beforeId)
            } else if(l_opt.type === 'fill') {

                this.addFillLayer(l_opt, beforeId)
            } else if (l_opt.type === 'circle') {
                this.addCircleLayer(l_opt)
            } else {
                this.addLayerCustomOption(l_opt, beforeId)
            }
        })
    }

    addLayerCustomOption(options, beforeId) {
        this.map.addLayer({...options}, beforeId)
    }

    // 添加矢量瓦片图层
    addVectorLayer(key, sourceOptions, layerOption, beforeId) {
        let s_opt = {
            promoteId: 'id',
            maxZoom: 22,
            minZoom: 0,
            // tiles: [
            //     "http://a.example.com/tiles/{z}/{x}/{y}.pbf",
            //     "http://b.example.com/tiles/{z}/{x}/{y}.pbf"
            // ]
        }
        Object.assign(s_opt, sourceOptions)
        this.map.on('load', () => {
            this.map.addSource(key, {...s_opt});

            let l_opt = {
                id: key,
                source: key,
                type: 'line'
            }
            Object.assign(l_opt, layerOption)
            if (l_opt.type === 'line') {
                // delete l_opt['type']
                this.addLineLayer(l_opt)
            } else if (l_opt.type === 'fill'){
                this.addFillLayer(l_opt)
            } else if (l_opt.type === 'circle') {
                this.addCircleLayer(l_opt)
            } else {
                this.addLayerCustomOption(l_opt, beforeId)
            }
        })
    }

    /**
     * 添加图层 图层类型为circle
     * @param options 配置项
     * @param beforeId
     */
    addCircleLayer(options, beforeId) {
        let opt = {}
        Object.assign(opt, options)
        const { paint, layout } = this.pointStyle(opt)
        if (!opt.id.startsWith(`${opt.type}_`)) {
            opt.id = opt.id.slice(0, 0) + opt.type + '_' + opt.id.slice(0);
        }
        this.map.addLayer({
            ...opt,
            paint,
            layout
        }, beforeId)
        this.layerMap.addLayer(opt.id, this.map.getLayer(opt.id))
    }

    /**
     * 添加图层 图层类型为line
     * @param options 配置项
     * @param beforeId
     */
    addLineLayer(options, beforeId) {
        let opt = {}
        Object.assign(opt, options)
        const { paint, layout } = this.lineStyle(opt)
        if (!opt.id.startsWith(`${opt.type}_`)) {
            opt.id = opt.id.slice(0, 0) + opt.type + '_' + opt.id.slice(0);
        }
        this.map.addLayer({
            ...opt,
            paint,
            layout
        }, beforeId)

        const layer = this.map.getLayer(opt.id)
        this.layerMap.addLayer(opt.id, layer)
        // this.map.on('click',opt.id, (e) => {
        //     console.log('瓦片', e.features[0].properties)
        //     console.log('瓦片', e.features[0])
        //     this.map.setPaintProperty(opt.id, 'line-color', '#ff0000');
        //
        // })
    }
    addClickEvent(e) {

    }
    /**
     * 添加图层 图层类型为 fill
     * @param options 配置项  需要额外外边框图层的 outlineOption: { id: '', ...线样式}, id是必须的 图层id
     * @param beforeId
     */
    addFillLayer(options, beforeId) {
        let opt = {}
        Object.assign(opt, options)
        // 如果需要控制polygon的外边框的话设置 outlineOption
        // outlineOption = { id: number, ...线的配置项 }
        if (opt.outlineOption) {
            const outlineOption  = JSON.parse(JSON.stringify(opt.outlineOption))
            const { paint, layout } = this.polygonStyle(opt)
            if (!opt.id.startsWith(`${opt.type}_`)) {
                opt.id = opt.id.slice(0, 0) + opt.type + '_' + opt.id.slice(0);
            }
            this.map.addLayer({
                ...opt,
                paint,
                layout
            }, beforeId)

            this.layerMap.addLayer(opt.id, this.map.getLayer(opt.id))
            const { paint: linePaint, layout: lineLayout } = this.lineStyle(outlineOption)

            if (!outlineOption.id.startsWith(`${opt.type}_outline_`)) {
                outlineOption.id = outlineOption.id.slice(0, 0) + `${opt.type}_outline_` + outlineOption.id.slice(0);
            }
            this.map.addLayer({
                ...opt,
                type: 'line',
                id: outlineOption.id,
                paint: linePaint,
                layout: lineLayout
            })
            this.layerMap.addLayer(outlineOption.id, this.map.getLayer(outlineOption.id))
        } else  {
            const { paint, layout } = this.polygonStyle(opt)
            if (!opt.id.startsWith(`${opt.type}_`)) {
                opt.id = opt.id.slice(0, 0) + opt.type + '_' + opt.id.slice(0);
            }
            this.map.addLayer({
                ...opt,
                paint,
                layout
            }, beforeId)
            this.layerMap.addLayer(opt.id, this.map.getLayer(opt.id))
        }
    }

    // 添加image图层
    addImageLayer() {}

    // 添加video图层
    addVideoLayer() {}

    /**
     * 点的样式
     * @param option 图层类型为circle
     * @returns {{layout: {}, paint: {"circle-color": string, "circle-radius": number}}}
     */
    pointStyle(option) {
        let paint_fields = ['circle-blur','circle-color','circle-opacity','circle-pitch-alignment','circle-pitch-scale','circle-radius','circle-stroke-color','circle-stroke-opacity','circle-stroke-width','circle-translate','circle-translate-anchor']
        let layout_fields = ['circle-sort-key', 'visibility']
        const { paint: copy_paint, layout: copy_layout } = this.separatePaintLayout(option, paint_fields, layout_fields)
        let paint = {
            'circle-color': '#eee30f',
            'circle-radius': 5
        }
        Object.assign(paint, copy_paint)
        let layout = {}
        Object.assign(layout, copy_layout)
        return {
            paint,
            layout
        }

    }

    /**
     * 线的样式
     * @param option 图层类型为line
     * @returns {{layout: {"line-join": string, "line-cap": string}, paint: {"line-width": number, "line-gap-width": number, "line-blur": number, "line-color": string}}}
     */
    lineStyle(option) {
        let paint_fields = ['line-blur','line-color','line-dasharray','line-gap-width','line-gradient','line-offset','line-opacity','line-pattern','line-translate','line-translate-anchor','line-trim-offset','line-width']
        let layout_fields = ['line-cap','line-join','line-miter-limit','line-round-limit','line-sort-key','visibility']
        // let copy_paint = {}
        // let copy_layout = {}
        // Object.keys(option).forEach(item => {
        //     if (paint_fields.includes(item)) {
        //         copy_paint[item] = option[item]
        //         delete option[item]
        //     }
        //     if (layout_fields.includes(item)) {
        //         copy_layout[item] = option[item]
        //         delete option[item]
        //     }
        // })
        const { paint: copy_paint, layout: copy_layout } = this.separatePaintLayout(option, paint_fields, layout_fields)
        let paint = {
            'line-color': '#f50808',
            'line-blur': 0,
            'line-gap-width': 0,
            'line-width': 3
        }
        Object.assign(paint, copy_paint)
        let layout = {
            'line-join': 'round',
            'line-cap': 'round', // 线段起始样式
        }
        Object.assign(layout, copy_layout)
        return {
            paint,
            layout
        }
    }

    /**
     * polygon样式 图层类型为 fill
     * @param option 配置项
     * @returns {{layout: {"line-join": string, "line-cap": string}, paint: {"line-width": number, "line-gap-width": number, "line-blur": number, "line-color": string}}}
     */
    polygonStyle(option) {
        let paint_fields = ['fill-antialias','fill-color','fill-opacity','fill-outline-color','fill-patter','fill-translate','fill-translate-anchor']
        let layout_fields = ['fill-sort-key','visibility']
        const { paint: copy_paint, layout: copy_layout } = this.separatePaintLayout(option, paint_fields, layout_fields)
        let paint = {
            'fill-color': 'rgba(126,216,224,0.72)',
            'fill-outline-color': '#2876c5',
        }
        Object.assign(paint, copy_paint)
        let layout = {}
        Object.assign(layout, copy_layout)
        return {
            paint,
            layout
        }
    }

    /**
     * layout的paint和layout配置项分开
     * @param options   配置项
     * @param paint_fields  所对应type的 paint的全部参数
     * @param layout_fields 所对应type的 layout的全部参数
     * @returns {{layout: {}, paint: {}}}
     */
    separatePaintLayout(options, paint_fields, layout_fields) {
        let paint = {}
        let layout = {}
        Object.keys(options).forEach(item => {
            if (paint_fields.includes(item)) {
                paint[item] = options[item]
                delete options[item]
            }
            if (layout_fields.includes(item)) {
                layout[item] = options[item]
                delete options[item]
            }
        })
        return {
            paint,
            layout
        }
    }

    /**
     * 添加Marker图层
     * @param point 位置
     * @param key   唯一值
     * @param option  配置项
     */
    addMarkerLayer(point, key, option) {
        debugger
        if (!key.startsWith('marker_')) {
            key = key.slice(0, 0) + 'marker_' + key.slice(0);
        }
        const Mark = new Marker(option, this.map)
        const marker = Mark.setMarker(point)
        try {
            this.layerMap.addLayer(key,marker)
            return marker.getElement()
        } catch (error) {
            marker.remove()
            console.log(error)
        }
    }


    addMarkerWithPopup(point, key, markerOption, popupOption) {
        if (!key.startsWith('marker_')) {
            key = key.slice(0, 0) + 'marker_' + key.slice(0);
        }
        const Mark = new Marker(markerOption, this.map)
        const { mark, popup } = Mark.setMarkerWithPopup(point, popupOption)
        try {
            this.layerMap.addLayer(key,mark)
            let popupKey = key + '_popup'
            this.layerMap.addLayer(popupKey,popup)
        } catch (error) {
            mark.remove()
            popup.remove()
            console.log(error)
        }
    }

    /**
     * 移除marker图层
     * @param key
     */
    removeMarkerLayer(key) {
        try {
            const value = this.layerMap.getLayer(key)
            value.remove()
            this.layerMap.removeLayer(key)
        } catch (error) {
            console.log(error)
        }
    }

    /**
     * 移除图层
     * @param key
     */
    removeLayer(key) {
        this.map.removeLayer(key)
        this.layerMap.removeLayer(key)
    }

}
export default LayerManager
